--- title: Spatial Data Visualisation in R author: 'Arnav ' date: '2018-04-07' slug: spatial-data-visualisation-in-r categories: - R tags: - spatial data analysis - leaflet - shapefile - geojson - crime mapping ---
The blog post covers plotting spatial points on a map in R. I will be covering the concepts of shapefiles, GeoJSON, Leaflets and sp objects and to how to read and manipulate them in R. At the end you would have created the following three interactive spatial maps 1. Pinpoint/Marker maps
Heat maps
Choropleth maps
First let’s take a look at what shapefiles or GeoJson files and ‘sp’ objects actually are.
Shapefile and GeoJson Shapefile and GeoJson are file types storing the spatial data and associated geographical features. You can imagine them to be a dataframe with data stored as information of spatial distribution of points, lines and polygons lying in the the geographical region which that shapefile/GeoJson describes. Points in a Shapefile/GeoJson can represent points or geo-cordinates on a map, lines can represent rivers, roads etc and polygons can correspond to enclosed blocks of areas on a map. For example:

Here, this shapefile has data stored in the form of spatial distribution of points ( indicating the wells), lines (denoting river) and polygon (denoting the lake here) in the region shown.
We would need a shapefile/geojson which would ultimately be converted into an sp object to map our spatial points on. Spatial (‘sp’) Objects sp is a package in R that provides classes and methods for dealing with spatial data. As discussed above, in spatial analysis, we crudely deal with the study of distribution of points, lines and polygons over a specific geographical region. ‘sp’ package can be considered to provide a class or a data type for storing such data. Thus an sp object is nothing but a variable of sp class.
Reading Shapefile/GeoJson into R and converting them into ‘sp’ or spatial object We would need Sh There are three easy ways to do this in R: 1. Reading GeoJson as sp object using ‘geojsonio’ from leaflet package 2. Reading Shapefile as sp object using ‘shapefile’ fucntion from raster package 3. Reading shapefile as sp object using ‘readOGR’ function from rgdal package.
Let’s load the required libraries first.
library(rgdal)# 1required for readOGR fucntion
library(raster)# 2required for shapefile function
library(leaflet) # 3 reading geojson
#library(dplyr) # required for as_tibble function
library(leaflet.extras) # required for generating heatmaps
The link for the required shapefiles/geojson is LINK
All the three maps read above would be of class ‘sp’. Let’s verify it once.
# Class types of all the three maps is 'sp'
class(assam_map)
## [1] "SpatialPolygonsDataFrame"
## attr(,"package")
## [1] "sp"
class(assam_map1)
## [1] "SpatialPolygonsDataFrame"
## attr(,"package")
## [1] "sp"
class(assam_map2)
## [1] "SpatialPolygonsDataFrame"
## attr(,"package")
## [1] "sp"
Also notice that all these three objects are SpatialPolygonDataFrame. That’s because these maps contain information on distribution on polygons, which denote districts in Assam in our demo. We will use ‘assam_map’ for our demo, though, any of the three would work fine. Let’s explore this ‘sp’ object assam_map further
library(ggplot2)
plot(assam_map)

library(dplyr) # For as_tibble function
as_tibble(assam_map)
## # A tibble: 27 x 5
## DISTRICT DT_CEN_CD ST_CEN_CD ST_NM censuscode
## * <fct> <int> <int> <fct> <int>
## 1 Baksa 25 18 Assam 324
## 2 Barpeta 4 18 Assam 303
## 3 Bongaigaon 20 18 Assam 319
## 4 Cachar 17 18 Assam 316
## 5 Chirang 21 18 Assam 320
## 6 Darrang 26 18 Assam 325
## 7 Dhemaji 9 18 Assam 308
## 8 Dhubri 2 18 Assam 301
## 9 Dibrugarh 11 18 Assam 310
## 10 Goalpara 3 18 Assam 302
## # ... with 17 more rows
The data I would be using for this demo is synthetic. It’s the same data I had used for the Satark Analytics Web App. You can find the csv file here LINKKKKK
#Load in your crime data
crimeData<-read.csv("assamcrimedata.csv")
crimeDemo<-crimeData[1:10,]
#Get an ovrview of crimeDemo
as_tibble(crimeDemo)
## # A tibble: 10 x 7
## dates crimetype lat lng crimedistricts victim_age victim_gender
## * <fct> <fct> <dbl> <dbl> <fct> <int> <fct>
## 1 2017-0~ Other theft 26.8 93.5 Sonitpur 15 M
## 2 2017-0~ Other theft 26.5 91.6 Kamrup 5 M
## 3 2017-0~ Drugs 26.2 91.3 Kamrup NA ""
## 4 2017-0~ Shoplifting 26.6 93.4 Golaghat NA ""
## 5 2017-0~ Shoplifting 26.6 92.0 Udalguri NA ""
## 6 2017-0~ Anti-socia~ 26.5 90.5 Chirang NA ""
## 7 2017-0~ Other theft 26.1 93.9 Golaghat 21 F
## 8 2017-0~ Bicycle th~ 26.9 94.0 Lakhimpur 7 F
## 9 2017-0~ Other theft 26.1 90.6 Goalpara 19 F
## 10 2017-0~ Other theft 26.2 91.5 Kamrup 47 M
Leaflet is a JavaScript library to create interactive maps. Find more details here Leaflet for R.
The ‘leaflet()’ function generates a map widget, which stores a list of objects. It mostly takes a map as an input, but can also take data frames or matrices having latitude and longitude as inputs.
For our purpose we would be giving a SpatialPolygonDataFrame (assam_map) as input. The map widget generated then could be considered as the final map which is ready to be plotted.
assam_leaflet<-leaflet(assam_map) %>% addPolygons()
assam_leaflet
This is the Assam leaflet we obtain. Let’s make it a little better looking.
assam_leaflet<-leaflet(assam_map) %>% addPolygons(color="#444444",weight=1)
assam_leaflet
Thus our leaflet is ready to be mapped upon. It’s time to move onto the last step.
Pinpoint or Marker plotting We will be marking up the crime points from our crimeDemo dataset onto the leaflet we have generated in the last step. We will be using the addMarkers function for the same.
assamMarker<-assam_leaflet %>%
addMarkers(data = crimeDemo,~lng, ~lat)
assamMarker
Let’s further add the functionality of generating a popup table when these markers are being clicked.
library(mapview) # for generating popupTable
assamMarker<-assam_leaflet %>%
addMarkers(data = crimeDemo,~lng, ~lat,popup= popupTable(crimeDemo))
assamMarker
Heatmap
library(leaflet.extras) # required for addHeatmap function
assamHeatmap<-assam_leaflet %>%
addHeatmap(data= crimeDemo,lng=~lng, lat=~lat,
blur = 20, max = 0.05, radius = 15 )
assamHeatmap
Choropleth
Generating chorpleth can be tricky. I would strongly urge you to checkout the documentation page for leaflet choropleth
Firstly, we need to process the crimeData (we won’t be using crimeDemo here because it contains to few a points for proper demonstration of a chorpleth). We need to build a count table which contains the district and the count of crimes taking place against every district. This can be easily done using the ‘count()’ function in R.
districtCrimeCount<-count(crimeData,vars=crimedistricts)
head(districtCrimeCount)
## # A tibble: 6 x 2
## vars n
## <fct> <int>
## 1 Baksa 16
## 2 Barpeta 15
## 3 Bongaigaon 6
## 4 Chirang 12
## 5 Darrang 8
## 6 Dhubri 7
Next, we generate three utility containers as foloows: bins : will help us to generate the color palette. Each bin interval will be assigned a different color in the palette. pal : to decide the color-coding scheme with respect to the number of crimes labels : to generate the interactive labels that appear on hovering over the map
bins <- c(0,3,6,9, 12, 15, 18, 21, 24,27,30,Inf)
pal <- colorBin("YlOrRd", domain = districtCrimeCount$n, bins = bins)
labels <- sprintf(
"<strong>%s</strong><br/>%g Crimes ",
districtCrimeCount$vars, districtCrimeCount$n
) %>% lapply(htmltools::HTML)
Next, we generate the choropleth by manipulating the addPolygons() function as follows
assam_choropleth<-assam_leaflet %>% addPolygons(
fillColor = ~pal(districtCrimeCount$n),
weight = 2,
opacity = 1,
dashArray = "3",
color = "white",
fillOpacity = 0.7,
highlight = highlightOptions(
weight = 5,
color = "#666",
bringToFront = TRUE),
label = labels) %>%
addLegend(pal = pal, values = ~n, opacity = 0.7, title = NULL,
position = "bottomright")
assam_choropleth